if
邏輯區塊if
邏輯區塊語法if
邏輯區塊 經過了三天的消化,我們知道了該如何運用 Svelte 提供的 each
邏輯區塊,讓我們可以運用類似 Javascript forEach
的邏輯運算,快速地根據 Javascript 陣列變數做出重複的 HTML 元素。是不是非常的方便又實用呢?今天就讓我們再接再厲,繼續學另一種 Svelte 所提供的邏輯區塊吧。
if
邏輯區塊語法一般的 HTML 並沒辦法提供條件式的運算來決定哪些 HTML 元素需要呈現給使用者,又是哪些 HTML 元素需要移除掉。但是為了能夠做出互動式 (reactive) 的使用者介面,這看起來是個不可或缺的功能。作為一個受到眾多工程師們喜愛的前端框架,Svelte 理所當然的能夠實現這個願望。程式碼的寫法如下:
{#if expression}
<!-- 將需要的 HTML 元素放在這裡 -->
{/if}
第一行:{#if expression}...{/if}
用 {#if}
開啟邏輯段落。expression
則是 Javascript 的表達式,能夠算出一個 true
或是 false
的結果。
第二行:<!-- 將需要的 HTML 元素放在這裡 -->
如果前面 expression
的值,經過布林值的轉換,結果為 true
,就會在呈現給使用者看的介面當中加入這邊的 HTML 元素。反之,如果為 false
,就不會出現這些 HTML 元素。
第三行:{/if}
記得要用 {/if}
結束這個邏輯段落。
既然有 if
的邏輯段落,那想必會有跟 else
邏輯段落的組合囉:
{#if expression}
<!-- 如果 expression 為 true,則顯示這邊的 HTML 元素 -->
{:else}
<!-- 否則顯示這邊的 HTML 元素 -->
{/if}
第一行:{#if expression}
用 {#if}
開啟邏輯段落。接著不贅述。
第二行:<!-- 如果 expression 為 true,則顯示這邊的 HTML 元素 -->
如果前面 expression
的值,經過布林值的轉換,結果為 true
,就會在呈現給使用者看的介面當中加入這邊的 HTML 元素。
第三行:{:else}
用 {:else}
將 if
這個邏輯段落做展延。
第四行:<!-- 否則顯示這邊的 HTML 元素 -->
如果前面 expression
的值,經過布林值的轉換,結果為 false
,就會在呈現給使用者看的介面當中加入這邊的 HTML 元素。
第五行:{/if}
最後,還是記得要用 {/if}
結束這個邏輯段落。
既然有 if
跟 else
的邏輯段落,那想必又會再有 else if
邏輯段落的組合囉:
{#if expression1}
<!-- 如果 expression1 為 true,則顯示這邊的 HTML 元素 -->
{:else if expression2}
<!-- 如果 expression2 為 true,則顯示這邊的 HTML 元素 -->
{/if}
第一行:{#if expression}
用 {#if}
開啟邏輯段落。接著不贅述。
第二行:<!-- 如果 expression1 為 true,則顯示這邊的 HTML 元素 -->
如果 expression1
的值,經過布林值的轉換,結果為 true
,就會在呈現給使用者看的介面當中加入這邊的 HTML 元素。
第三行:{:else if expression2}
用 {:else}
將 if
這個邏輯段落做展延,並繼續做第二個條件 expression2
的計算。
第四行:<!-- 否則顯示這邊的 HTML 元素 -->
如果 expression2
的值,經過布林值的轉換,結果為 true
,就會在呈現給使用者看的介面當中加入這邊的 HTML 元素。
第五行:{/if}
最後,還是記得要用 {/if}
結束這個邏輯段落。
既然有 if
跟 else
跟 else if
的邏輯段落,那想必又會再有沒完沒了的各種組合囉?沒錯,Svelte 就是提供了一個這麼富有彈性又方便的 if
邏輯段落。
if
邏輯區塊 學到一個這麼好用的工具,不實際來運用看看豈不可惜。就讓我們試試看用 if
邏輯區塊去動態顯示色票的鎖定跟解除鎖定的狀態吧。直接來到 Palettes.svelte
的程式碼:
/src/lib/Palettes.svelte
<script>
import unlock from "../assets/unlock.svg";
import lock from "../assets/lock.svg";
export let palettes;
</script>
<div class="palettes">
{#each palettes as { hex, id, locked } (id)}
<div class="card">
<div class="palette" style="background: #{hex}" />
<div class="hex-code">
<p>
{hex}
</p>
</div>
<!-- svelte-ignore a11y-no-static-element-interactions a11y-click-events-have-key-events -->
<div class="lock-icon">
{#if locked}
<img src={lock} alt="color-locked" />
{:else}
<img src={unlock} alt="color-unlocked" />
{/if}
</div>
</div>
{:else}
<div class="card no-color">
<div>
<p>No color to show. Please add a color.</p>
</div>
</div>
{/each}
</div>
第三行:import lock from "../assets/lock.svg";
為了要表達鎖定色票的狀態,我們同樣也從 Font Awesome 參考了上鎖的圖示。詳細的程式碼可以參考 Font Awesome 的網站(這裡)。
第八行:{#each palettes as { hex, id, locked } (id)}
因為我們需要從 palettes
每個物件當中的 locked
這個鍵值 (key) 來判斷該色票是否為鎖定的狀態,所以記得用解構賦值把 locked
也拿出來。
第十八行:{#if locked}
用 {#if}
開啟 if
的邏輯段落。並且用 locked
這個變數的布林值來做為顯示 HTML 元素的依據。
第十九行:<img src={lock} alt="color-locked" />
如果 locked
這個布林值為 true
,則顯示上鎖這個圖示。
第二十行:{:else}
用 {:else}
展延出 else
的邏輯段落。
第二十一行:<img src={unlock} alt="color-unlocked" />
如果 locked
的布林值為 false
,則顯示解鎖這個圖示。
第二十二行:{/if}
記得用 {/if}
來結束整個 if
邏輯段落。
雖然把 if
邏輯段落做好了,但是仔細檢視看看我們的專案,應該就會注意到現在所有色票的 locked
都為 false
,這樣就看不出來 if
邏輯段落是否符合我們所設計的方式去運作。讓我們把新增的色票的 locked
都改成 true
試試看吧:
/src/App.svelte
<!-- 在 Javascript 當中 import Counter -->
<script>
import Counter from "./lib/Counter.svelte";
import Modal from "./lib/Modal.svelte";
import Palettes from "./lib/Palettes.svelte";
let showModal = false;
let palettes = [
{ hex: "ff4000", locked: false, id: "init_01" },
{ hex: "32e6e3", locked: false, id: "init_02" },
{ hex: "009fe9", locked: false, id: "init_03" },
];
$: count = palettes.length;
const generateTone = () =>
("0" + Math.round(255 * Math.random()).toString(16)).slice(-2);
const generateHex = () =>
[generateTone(), generateTone(), generateTone()].reduce(
(a, c) => a + c,
""
);
const generatePalette = (() => {
let uuid = 0;
return () => ({
hex: generateHex(),
locked: true,
id: `${uuid++}`,
});
})();
let someState = "TheGreatSvelte";
const sparkle = (text) => {
const sparkles = ["★", "☆", "✧", "✪"];
const randomSparkles = () =>
sparkles[Math.floor(Math.random() * sparkles.length)];
const sparkledText = text
.split("")
.reduce((a, c) => a + randomSparkles() + c, "");
return sparkledText;
};
const href = "https://ithelp.ithome.com.tw/users/20120178/ironman/7031";
const handleClick = (e) => {
console.log(e);
const tobeCount = count + e.detail;
if (0 <= tobeCount && tobeCount < 7) {
switch (e.detail) {
case 1:
palettes = [...palettes, generatePalette()];
break;
case -1:
palettes = palettes.slice(0, -1);
break;
}
} else showModal = true;
};
</script>
這麼一大段程式碼,有改變的只有這一行:
locked: true,
locked
變成 true
吧。
圖一,新增的色票都給他鎖起來
太棒了,看來我們做出來的 if
邏輯段落是真的有發揮作用的。那麼野心勃勃的人,是不是想要更進一步去實作互動的功能,讓使用者可以藉由點擊這個上鎖/解鎖圖示,來改變上鎖/解鎖的狀態呢?沒問題,讓我們藉由第十三天學過的客製化事件來完成這個任務吧:
/src/lib/Palettes
<script>
import { createEventDispatcher } from "svelte";
import unlock from "../assets/unlock.svg";
import lock from "../assets/lock.svg";
export let palettes;
const dispatch = createEventDispatcher();
const handleClick = (id) => dispatch("changeLock", id);
</script>
<div class="palettes">
{#each palettes as { hex, id, locked } (id)}
<div class="card">
<div class="palette" style="background: #{hex}" />
<div class="hex-code">
<p>
{hex}
</p>
</div>
<!-- svelte-ignore a11y-no-static-element-interactions a11y-click-events-have-key-events -->
<div class="lock-icon" on:click={() => handleClick(id)}>
{#if locked}
<img src={lock} alt="color-locked" />
{:else}
<img src={unlock} alt="color-unlocked" />
{/if}
</div>
</div>
{:else}
<div class="card no-color">
<div>
<p>No color to show. Please add a color.</p>
</div>
</div>
{/each}
</div>
第二行:import { createEventDispatcher } from "svelte";
引入客製化事件需要的 createEventDispatcher
第七行:const dispatch = createEventDispatcher();
初始化客製化事件產生器。
第八行:const handleClick = (id) => dispatch("changeLock", id);
客製化一個 changeLock
事件,隨著該事件傳送出 id
的資訊,讓我們主要元件 (App.svelte
) 能夠知道應該改變哪一個色票的 locked
狀態。
第二十一行:<div class="lock-icon" on:click={() => handleClick(id)}>
在這個 <div>
上加上我們的事件處理器 handleClick
,只要一點擊,就發送 changeLock
事件。
接著來到我們的 App.svelte
,需要做些修改,來接收子元件 Palettes.svelte
發送過來的 changeLock
事件:
/src/App.svelte
<!-- 在 Javascript 當中 import Counter、Modal、Palettes -->
<script>
import Counter from "./lib/Counter.svelte";
import Modal from "./lib/Modal.svelte";
import Palettes from "./lib/Palettes.svelte";
let showModal = false;
let palettes = [
{ hex: "ff4000", locked: false, id: "init_01" },
{ hex: "32e6e3", locked: false, id: "init_02" },
{ hex: "009fe9", locked: false, id: "init_03" },
];
$: count = palettes.length;
const generateTone = () =>
("0" + Math.round(255 * Math.random()).toString(16)).slice(-2);
const generateHex = () =>
[generateTone(), generateTone(), generateTone()].reduce(
(a, c) => a + c,
""
);
const generatePalette = (() => {
let uuid = 0;
return () => ({
hex: generateHex(),
locked: true,
id: `${uuid++}`,
});
})();
let someState = "TheGreatSvelte";
const sparkle = (text) => {
const sparkles = ["★", "☆", "✧", "✪"];
const randomSparkles = () =>
sparkles[Math.floor(Math.random() * sparkles.length)];
const sparkledText = text
.split("")
.reduce((a, c) => a + randomSparkles() + c, "");
return sparkledText;
};
const href = "https://ithelp.ithome.com.tw/users/20120178/ironman/7031";
const handleClick = (e) => {
console.log(e);
const tobeCount = count + e.detail;
if (0 <= tobeCount && tobeCount < 7) {
switch (e.detail) {
case 1:
palettes = [...palettes, generatePalette()];
break;
case -1:
palettes = palettes.slice(0, -1);
break;
}
} else showModal = true;
};
const handleLock = (e) => {
console.log(e);
const targetId = e.detail;
palettes = palettes.map((palette) => {
if (palette.id === targetId) {
return { ...palette, locked: !palette.locked };
} else {
return palette;
}
});
};
</script>
第六十一行:const handleLock = (e) => {
宣告一個函式 handleLock
,用來處理 changeLock
事件。這個函式需要用我們的客製化事件當作參數,所以在參數的部分寫一個 e
代表。
第六十二行:console.log(e);
將事件 e
記錄下來。單純方便偵錯使用,不一定需要這一行。
第六十三行:const targetId = e.detail;
我們伴隨客製化事件 changeLock
一起送出來的資料會放在哪邊呢?就是在 e.detail
當中,所以用 targetId
將目標的 id
儲存起來。接下來的程式碼就不細講了。大意就是在 palettes
當中找出 id === targetId
的色票,並切換該色票的 locked
布林值。原本為 true
的就變成 false
,原本為 false
的就變成 true
。
圖二、三個可以自由解鎖/開鎖的色票
好的,那麼今天關於 if
邏輯段落的介紹就到這邊了,謝謝大家。